package com.tianyadu.mmall.controller;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonView;
import com.tianyadu.mmall.entity.FileInfo;
import com.tianyadu.mmall.entity.Person;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 测试用户
 *
 * @author xueyj
 * @date 2019-10-20 01:03
 */
@Slf4j
@RestController
@RequestMapping("/person")
public class PersonController {

    /**
     * 文件上传路径
     */
    private String folder = "E:/mmall/demo/src/main/java/com/tianyadu/mmall/demo/controller";

    /**
     * 模拟测试用户请求，多方式传参，单参数，实体传参，分页传参
     *
     * @param id         测试id
     * @param personInfo 测试用户信息
     * @param pageable   测试分页信息
     * @return
     */
    @GetMapping
    @JsonView(Person.PersonSimpleView.class)
    public List<Person> findPersonInfo(@RequestParam(value = "id") int id, Person personInfo,
                                       @PageableDefault(page = 1, size = 10, sort = "age,desc") Pageable pageable) {
        log.info("模拟测试用户请求入参，id =【{}】,userInfo =【{}】，pageable.page =【{}】，pageable.size =【{}】", id,
                JSON.toJSONString(personInfo), pageable.getPageNumber(), pageable.getPageSize());
        List<Person> personList = new ArrayList<>();
        personList.add(new Person());
        personList.add(new Person());
        personList.add(new Person());
        personList.add(new Person());
        return personList;
    }

    /**
     * 模拟根据用户id查询信息，用户id使用正则表达式校验(需为数字)
     *
     * @param personId 测试id
     */
    @GetMapping("{id:\\d+}")
    @JsonView(Person.PersonDetailView.class)
    public Person findPersonInfoById(@PathVariable(value = "id") String personId) {
        log.info("模拟根据用户id查询信息入参，personId =【{}】", personId);
        Person person = new Person();
        person.setId(personId);
        person.setUsername("tom");
        return person;
    }

    /**
     * 模拟用户添加
     *
     * @param person 用户信息
     * @return com.tianyadu.mmall.user.demo.pojo.UserInfo
     * @author xueyj
     * @date 2019/9/19-23:55
     */
    @PostMapping
    public Person createPerson(@Valid @RequestBody Person person, BindingResult bindingResult) {
        log.info("模拟用户添加入参，userInfo=【{}】", JSON.toJSONString(person));
        //  校验入参是否符合规则，若不符合，打印异常信息
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors().stream().forEach(e ->
            {
                FieldError fieldError = (FieldError) e;
                String field = fieldError.getField();
                String defaultMessage = fieldError.getDefaultMessage();
                System.out.println("失败内容：" + field + ";失败信息：" + defaultMessage);
            });
        }
        person.setId("1");
        person.setUsername("JOJO");
        return person;
    }

    /**
     * 模拟用户添加
     *
     * @param person 用户信息
     * @return com.tianyadu.mmall.user.demo.pojo.UserInfo
     * @author xueyj
     * @date 2019/9/19-23:55
     */
    @PostMapping("/noBindingResult")
    public Person createPersonInfo(@Valid @RequestBody Person person) {
        log.info("模拟用户添加入参，userInfo=【{}】", JSON.toJSONString(person));
        person.setId("1");
        person.setUsername("JOJO");
        return person;
    }

    /**
     * 模拟用户修改
     *
     * @param person        用户信息
     * @param bindingResult 错误绑定信息
     * @return com.tianyadu.mmall.user.demo.pojo.Person
     * @author xueyj
     * @date 2019/9/20-23:19
     */
    @PutMapping("{id:\\d+}")
    public Person updatePersonInfo(@Valid @RequestBody Person person, BindingResult bindingResult) {
        log.info("模拟用户修改入参，userInfo=【{}】", JSON.toJSONString(person));
        //  校验入参是否符合规则，若不符合，打印异常信息
        boolean hasErrors = bindingResult.hasErrors();
        if (hasErrors) {
            bindingResult.getAllErrors().stream().forEach(e ->
            {
                FieldError fieldError = (FieldError) e;
                String field = fieldError.getField();
                String defaultMessage = fieldError.getDefaultMessage();
                System.out.println("失败内容：" + field + ";失败信息：" + defaultMessage);
            });
        }
        person.setId("1");
        person.setUsername("JOJO");
        return person;
    }

    /**
     * 删除用户
     *
     * @param personId 用户id
     * @author xueyj
     * @date 2019/9/20-23:22
     */
    @DeleteMapping("{id:\\d+}")
    public void deletePersonInfoById(@PathVariable(value = "id") String personId) {
        log.info("删除用户用户入参，personId=【{}】", personId);
    }

    /**
     * 文件上传
     *
     * @param file
     * @return com.tianyadu.mmall.user.demo.pojo.FileInfo
     * @author xueyj
     * @date 2019/9/21-23:27
     */
    @PostMapping("/file")
    public FileInfo upload(MultipartFile file) throws Exception {
        log.info("上传文件信息，文件名：【{}】，原始文件名：【{}】，文件size：【{}】",
                file.getName(), file.getOriginalFilename(), file.getSize());
        //  构建本地文件信息
        File localFile = new File(folder, System.currentTimeMillis() + ".txt");
        //  拷贝文件信息至本地文件
        file.transferTo(localFile);
        //  返回上传后的文件路径信息
        return new FileInfo(localFile.getAbsolutePath());
    }

    /**
     * 文件下载
     *
     * @param id
     * @param request
     * @param response
     * @return void
     * @author xueyj
     * @date 2019/9/21-23:29
     */
    @GetMapping("/file/{id}")
    public void download(@PathVariable(value = "id") String id, HttpServletRequest request, HttpServletResponse response) throws Exception {
        try (InputStream inputStream = new FileInputStream(new File(folder, id + ".txt"));
             OutputStream outputStream = response.getOutputStream();) {

            response.setContentType("application/x-download");
            response.addHeader("Content-Disposition", "attachment;filename=test.txt");

            IOUtils.copy(inputStream, outputStream);
            outputStream.flush();
        }
    }

}